<?php

/**
 * Unpack and import zip file. Each file/folder is imported as an individual
 * artefact.
 *
 * @copyright (c) 2012 University of Geneva
 * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
 * @author Laurent Opprecht <laurent@opprecht.info>
 */

class ImportArchive
{

    protected $path = '';
    protected $owner = 0;
    protected $group = 0;
    protected $institution = 0;
    protected $directories = array();
    protected $temp_files = array();

    public function __construct($path, $owner = null, $group = null, $institution = null)
    {
        global $USER;
        $this->path = $path;
        $this->owner = $owner ? $owner : $USER->get('id');
        $this->group = $group;
        $this->institution = $institution;
    }

    public function get_path()
    {
        return $this->path;
    }

    public function get_owner()
    {
        return $this->owner;
    }

    public function get_group()
    {
        return $this->group;
    }

    public function get_institution()
    {
        return $this->institution;
    }

    public function import()
    {
        if (!$this->is_zip()) {
            return false;
        }

        $result = array();
        $handle = zip_open($this->path);
        while ($entry = zip_read($handle)) {
            $path = zip_entry_name($entry);

            if ($this->is_dir($path)) {
                $dir = $this->get_directory($path);
                break;
            }
            $dir_name = $this->dir_name($path);
            $dir = $this->get_directory($dir_name);

            $temp_file = $this->temp_file();
            $size = zip_entry_filesize($entry);
            $content = zip_entry_read($entry, $size);
            file_put_contents($temp_file, $content);

            $data = (object) array();
            $data->owner = $this->get_owner();
            $data->title = $this->base_name($path);
            if ($dir) {
                $data->parent = $dir->get('id');
            }

            $user = null;
            $success = ArtefactTypeFile::save_file($temp_file, $data, $user, true);
            if ($success) {
                $result[] = $path;
            }
        }
        return $result;
    }

    function is_zip()
    {
        return ArtefactTypeArchive::is_zip($this->path);
    }

    function ext($path)
    {
        $parts = explode('.', $path);
        return count($parts) > 1 ? end($parts) : '';
    }

    function is_dir($path)
    {
        return (substr($path, -1) == '/');
    }

    function base_name($path)
    {
        $parts = explode('/', $path);
        return end($parts);
    }

    function dir_name($path)
    {
        $parts = explode('/', $path);
        if (count($parts) == 1) {
            return '';
        }

        array_pop($parts);
        return implode('/', $parts);
    }

    function temp_file()
    {
        $result = get_config('dataroot') . '/temp/' . md5(uniqid());
        $this->temp_files[] = $result;
        return $result;
    }

    /**
     *
     * @param string $path 
     * @return ArtefactTypeFolder
     */
    function get_directory($path)
    {
        if (empty($path)) {
            return null;
        }
        $path = rtrim($path, '/');
        $path = $path . '/';

        if (isset($this->directories[$path])) {
            return $this->directories[$path];
        }

        $dir = '';
        $parent = null;
        $parts = explode('/', $path);
        foreach ($parts as $part) {
            if (empty($part)) {
                break;
            }
            $dir .= $part . '/';
            if (isset($this->directories[$dir])) {
                $parent = $this->directories[$dir];
            } else {
                $folder = new ArtefactTypeFolder();
                $folder->set('owner', $this->get_owner());
                $folder->set('institution', $this->get_institution());
                $folder->set('group', $this->get_group());
                $folder->set('title', $part);
                if ($parent) {
                    $folder->set('parent', $parent->get('id'));
                }

                $folder->commit();
                $this->directories[$dir] = $folder;
                $parent = $folder;
            }
        }
        return $parent;
    }

    function __destruct()
    {
        foreach ($this->temp_files as $path) {
            unlink($path);
        }
    }

}